﻿using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using System.Text;
using UnityEngine;
using System.IO;
using System;
using UnityEngine.UI;
using System.Text.RegularExpressions;

public class UGUIAutoCreateScript : Editor
{
    static private string m_ViewPath = Application.dataPath + "/Scripts/View";
    static private string m_ModelPath = Application.dataPath + "/Scripts/Model";
    private static StringBuilder viewstringBuilder = new StringBuilder();
    private static StringBuilder modelstringBuilder = new StringBuilder();
    private static string dingyibianliang;
    static string awakeText;
    static string initfuncText;
    static string setdataText;
    static string addLisinersText;

    static string modelValueText;//模型层的变量
    static string modeLattributeText;//模型层的变量属性实现
    private static void SB_AddViewText(string scriptName)
    {
        viewstringBuilder.AppendLine("using System.Collections;");
        viewstringBuilder.AppendLine("using System.Collections.Generic;");
        viewstringBuilder.AppendLine("using UnityEngine;");
        viewstringBuilder.AppendLine("using UnityEngine.UI;");
        viewstringBuilder.AppendLine();
        modelstringBuilder.AppendLine("namespace EzFreamKowk{");
        viewstringBuilder.Append("public class ");
        viewstringBuilder.Append(scriptName);
        viewstringBuilder.Append(" : MonoBehaviour");
        viewstringBuilder.AppendLine();
        viewstringBuilder.AppendLine("{");
        viewstringBuilder.AppendLine("   //定义变量");
        viewstringBuilder.AppendLine("  private List<InputField> listInputField = new List<InputField>();//用来管理InputFild的容器");
        viewstringBuilder.Append(dingyibianliang);
        viewstringBuilder.AppendLine("  private void Awake() {");
        viewstringBuilder.Append(awakeText);
        viewstringBuilder.AppendLine("  InitFunc();      //获取组件");
        viewstringBuilder.AppendLine("  AddLisiners();//监听事件");
        viewstringBuilder.AppendLine("  }");
        viewstringBuilder.AppendLine();

        viewstringBuilder.AppendLine("//初始化函数 用于获取UI组件等");
        viewstringBuilder.AppendLine("  private void InitFunc() {");
        viewstringBuilder.Append(initfuncText);
        viewstringBuilder.AppendLine("  }");

        viewstringBuilder.AppendLine("  //将模型层的数据同步到View层");
        viewstringBuilder.AppendLine("  private void SetData() {");
        viewstringBuilder.AppendLine("  }");


        viewstringBuilder.AppendLine("//初始化函数 用于获取UI组件等");
        viewstringBuilder.AppendLine("  private void AddLisiners() {");
        viewstringBuilder.Append(addLisinersText);


        viewstringBuilder.AppendLine("      if(listInputField.Count>0)\n        {");
        viewstringBuilder.AppendLine("          foreach (InputField item in listInputField)\n           {");
        viewstringBuilder.AppendLine("              item.onValueChanged.AddListener(value =>{Debug.Log(item.name + \":\" + value);});");
        viewstringBuilder.AppendLine("              }");
        viewstringBuilder.AppendLine("       }");

        viewstringBuilder.AppendLine("  }");
        viewstringBuilder.AppendLine("}");
        modelstringBuilder.AppendLine("}");
       
        WriteStrToFile(viewstringBuilder.ToString(), m_ViewPath, scriptName);
    }
    
    /// <summary>
    /// 写入model文本
    /// </summary>
    /// <param name="scriptName"></param>
    private static void SB_AddModelText(string scriptName)
    {
        modelstringBuilder.AppendLine("using System.Collections;");
        modelstringBuilder.AppendLine("using System.Collections.Generic;");
        modelstringBuilder.AppendLine("using UnityEngine;");
        modelstringBuilder.AppendLine("using UnityEngine.UI;");
        modelstringBuilder.AppendLine("using System;");
        modelstringBuilder.AppendLine("namespace EzFreamKowk{");
        modelstringBuilder.Append("public class ");
        modelstringBuilder.Append(scriptName + "Model");
        modelstringBuilder.AppendLine("{");
        modelstringBuilder.AppendLine("public delegate void OnValueChangeEventHandle();");
        modelstringBuilder.AppendLine("private static " + scriptName + "Model" + " _Singleton = null;");
        modelstringBuilder.AppendLine("public static " + scriptName + "Model" + " Instance(){");
        modelstringBuilder.AppendLine("if (_Singleton == null)");

        modelstringBuilder.AppendLine(" {\n         _Singleton = new " + scriptName + "Model();\n         }\n         return _Singleton;");

        modelstringBuilder.AppendLine("}");

        modelstringBuilder.AppendLine("public event OnValueChangeEventHandle OnExperienceChange;");
        modelstringBuilder.AppendLine(modelValueText);
        modelstringBuilder.AppendLine(modeLattributeText);//属性定义

        modelstringBuilder.AppendLine("}");
        WriteStrToFile(modelstringBuilder.ToString(), m_ModelPath, scriptName + "Model");
        modelstringBuilder.AppendLine("}");
        
    }

    /// <summary>
    /// 写入模型变量
    /// </summary>
    private static void WriteModelBianLiang(GameObject gameObject)
    {
        List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
        //strlist.
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder1 = new StringBuilder();
        for (int i = 1; i < listTemp.Count; i++)
        {
            if (UIComponentToString(listTemp[i]) == "Text")
            {
                stringBuilder.AppendLine("    private string "+ FormartName(listTemp[i].name) + ";");
                stringBuilder1.AppendLine("    public string " + FormartName(listTemp[i].name) + "{");
                stringBuilder1.AppendLine("        get{ return " + FormartName(listTemp[i].name) + "; }");
                stringBuilder1.AppendLine("        set{"+ FormartName(listTemp[i].name) + " = value;" + " OnExperienceChange(); }");
                stringBuilder1.AppendLine("}");
            }
            string temp = FormartName(listTemp[i].name);
        }
        modelValueText = stringBuilder.ToString();
        modeLattributeText = stringBuilder1.ToString();
        Debug.Log("成功写入事件监听");
    }

    [MenuItem("GameObject/AutoCreateUGUIScript", priority = 0)]
    static void AutoCreateScript()
    {
        GameObject[] objTemp = Selection.gameObjects;
        //自动创建脚本
        if (objTemp != null && objTemp.Length >= 1)
        {
            WriteSetdataText(objTemp[0]);
            WriteBianLiang(objTemp[0]);
            WriteGetComponent(objTemp[0]);
            AddLisiners(objTemp[0]);
            SB_AddViewText(objTemp[0].name);
            GetAllChildGameObject(objTemp[0].transform);
            AssetDatabase.Refresh();
        }
        else
        {
            Debug.LogError("未选中任何物体，请选择一个UI面板");
        }
    }

    [MenuItem("GameObject/AutoCreateModel", priority = 0)]
    static void AutoCreateModel()
    {
        GameObject[] objTemp = Selection.gameObjects;
        //自动创建脚本
        if (objTemp != null && objTemp.Length >= 1)
        {
            WriteModelBianLiang(objTemp[0]);
            SB_AddModelText(objTemp[0].name);
            AssetDatabase.Refresh();
        }
        else
        {
            Debug.LogError("未选中任何物体，请选择一个UI面板");
        }
    }
    /// <summary>
    /// 自动创建模型层
    /// </summary>
    static void AutoCreateModelScript(GameObject gameObject)
    {
        SB_AddModelText(FormartName(gameObject.name) + "Model");
    }


    static void WriteStrToFile(string txt, string path, string fileName)
    {
        if (Directory.Exists(path) == false)
        {
            Directory.CreateDirectory(path);
        }
        if (string.IsNullOrEmpty(txt) || string.IsNullOrEmpty(path))
        {
            return;
        }
        File.WriteAllText(path + "/" + fileName + ".cs", txt, Encoding.UTF8);
    }

    static void WriteSetdataText(GameObject gameObject)
    {
        List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
        //strlist.
        StringBuilder stringBuilder = new StringBuilder();
        StringBuilder stringBuilder1 = new StringBuilder();
        StringBuilder stringBuilder2 = new StringBuilder();
        for (int i = 1; i < listTemp.Count; i++)
        {
            if (UIComponentToString(listTemp[i]) == "Text")
            {
                stringBuilder2.AppendLine("        " + FormartName(listTemp[i].name) + ".text = " + gameObject.name + "Model.Instance()." + FormartName(listTemp[i].name + ";"));//Text.text = LoadingPanelModel.Instance().Text;
            }
        }
        setdataText = stringBuilder2.ToString();
        Debug.Log("成功写入事件监听");
    }
    /// <summary>
    /// 添加UI事件监听
    /// </summary>
    static void AddLisiners(GameObject gameObject)
    {

        List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
        List<string> strlist = new List<string>();
        //strlist.
        StringBuilder stringBuilder = new StringBuilder();
        int x = 0;
        for (int i = 1; i < listTemp.Count; i++)
        {
            string temp = FormartName(listTemp[i].name);
            for (int j = 0; j < strlist.Count; j++)
            {
                if (strlist[j] == temp)
                {
                    x++;
                    temp = temp + x.ToString();
                }
            }
            strlist.Add(FormartName(listTemp[i].name));

            Filtration(listTemp, stringBuilder, i, temp);
        }
        addLisinersText = stringBuilder.ToString();
        Debug.Log("成功写入事件监听");
    }

    /// <summary>
    /// 过滤UI
    /// </summary>
    /// <param name="listTemp"></param>
    /// <param name="stringBuilder"></param>
    /// <param name="i"></param>
    /// <param name="temp"></param>
    private static void Filtration(List<GameObject> listTemp, StringBuilder stringBuilder, int i, string temp)
    {
        switch (UIComponentToString(listTemp[i]))
        {
            case "Button":
                stringBuilder.AppendLine("      " + temp + ".onClick.AddListener(" + "()=>{ \n       Debug.Log(\"" + listTemp[i] + "\");\n     });");
                break;
            case "Toggle":
                stringBuilder.AppendLine("      " + temp + ".onValueChanged.AddListener(" + "(e)=>{ \n       Debug.Log(\"" + listTemp[i] + ":" + "\"+e);\n     });");
                break;
            case "InputField":
                stringBuilder.AppendLine("      listInputField.Add(" + temp + ");");
                break;
            case "Text":
                break;
            default:
                Debug.Log("defult");
                break;
        }
    }

    /// <summary>
    /// 批量定义变量，遍历选中物体的子物体
    /// </summary>
    static void WriteBianLiang(GameObject gameObject)
    {
        List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
        List<string> strlist = new List<string>();
        StringBuilder stringBuilder = new StringBuilder();
        int x = 0;
        for (int i = 1; i < listTemp.Count; i++)
        {
            string temp = FormartName(listTemp[i].name);
            for (int j = 0; j < strlist.Count; j++)
            {
                if (strlist[j] == temp)
                {
                    x++;
                    temp = temp + x.ToString();
                    listTemp[i].name = temp;//更改物体名字
                }
            }
            strlist.Add(FormartName(listTemp[i].name));
            stringBuilder.AppendLine("  private " + UIComponentToString(listTemp[i]) + " " + temp + ";");//TODO
        }
        dingyibianliang = stringBuilder.ToString();
        Debug.Log("成功写入定义变量");
    }

    /// <summary>
    /// 获取所有子物体
    /// </summary>
    /// <param name="transform"></param>
    /// <returns></returns>
    private static List<GameObject> GetAllChildGameObject(Transform transform)
    {
        List<GameObject> gameObjects = new List<GameObject>();
        Transform[] father = transform.GetComponentsInChildren<Transform>();
        for (int i = 0; i < father.Length; i++)
        {
            gameObjects.Add(father[i].gameObject);
            Debug.Log(father[i].name);
        }
        return gameObjects;
    }

    /// <summary>
    /// 将变量名变成合法的形式 
    /// </summary>
    /// <returns></returns>
    private static string FormartName(string str)
    {
        string tempname =Regex.Replace(str, "[ \\[ \\] \\^ \\-_*×――(^)$%~!@#$…&%￥—+=<>《》!！??？:：•`·、。，；,.;\"‘’“”-]", "");//变量名防止出现标点符号
        return tempname;
    }

    /// <summary>
    /// 写入 获取组件代码
    /// </summary>
    private static void WriteGetComponent(GameObject gameObject)
    {
        List<GameObject> listTemp = GetAllChildGameObject(gameObject.transform);
        List<string> strlist = new List<string>();
        //strlist.
        StringBuilder stringBuilder = new StringBuilder();
        int x = 0;
        for (int i = 1; i < listTemp.Count; i++)
        {
            string temp =listTemp[i].name;
            //for (int j = 0; j < strlist.Count; j++)             //这一层循环是为了不出现同名的物体和变量
            //{
            //    if (strlist[j] == temp)
            //    {
            //        x++;
            //        temp = temp + x.ToString();
            //    }
            //}
            strlist.Add(FormartName(listTemp[i].name));
            stringBuilder.AppendLine("      " +FormartName(temp) + " = " + "ToolUnity.FindGameObject(gameObject,\"" + listTemp[i].name + "\").GetComponent<" + UIComponentToString(listTemp[i]) + ">();");
        }
        initfuncText = stringBuilder.ToString();
        Debug.Log("成功写入定义变量");
    }

    /// <summary>
    /// 将UI组件变成string类型
    /// </summary>
    /// <param name="gameObject"></param>
    /// <returns></returns>
    private static string UIComponentToString(GameObject gameObject)
    {
        if (gameObject.GetComponent<Button>())
        {
            return "Button";
        }
        if (gameObject.GetComponent<InputField>())
        {
            return "InputField";
        }
        if (gameObject.GetComponent<Scrollbar>())
        {
            return "Scrollbar";
        }
        if (gameObject.GetComponent<Image>())
        {
            return "Image";
        }
        else if (gameObject.GetComponent<RawImage>())
        {
            return "RawImage";
        }
        else if (gameObject.GetComponent<Text>())
        {
            return "Text";
        }
        else if (gameObject.GetComponent<Toggle>())
        {
            return "Toggle";
        }
        else if (gameObject.GetComponent<Dropdown>())
        {
            return "Dropdown";
        }
        else if (gameObject.GetComponent<Slider>())
        {
            return "Slider";
        }
        else
        {
            return "GameObject";
        }
    }
}
